module top(
	input clk,
	input resetn,
	output trap,
	output reg [7:0] out_byte,
	output reg out_byte_en,
    output clk_o,
    output mem_valid_o,
    output mem_ready_o,
    output [31:0] debug_reg_rdata,
    output uart_tx,
    input uart_rx,
    input [3:0] key//
);
/*
*  CH340 RX ----- FPGA 30 TX
*  CH340 TX ----- FPGA 31 RX
*/
wire mem_valid;
wire mem_instr;
wire [31:0] mem_addr;
wire [31:0] mem_wdata;
wire [3:0] mem_wstrb;

wire mem_ready;
wire [31:0] mem_rdata;

assign mem_valid_o = mem_valid;
assign mem_ready_o = mem_ready;

reg [4:0] debug_reg_rwaddr;
wire [31:0] riscv_pc;
reg cpu_reste;
riscv32 #(
		.STACKADDR(32'hffff_fff0)
	)picorv32_core(
	.clk      (clk      ),
    .resetn   (cpu_reste   ),
    .mem_valid(mem_valid),
    .mem_instr(mem_instr),
    .mem_ready(mem_ready),
    .mem_addr (mem_addr ),
    .mem_wdata(mem_wdata),
    .mem_wstrb(mem_wstrb),
    .mem_rdata(mem_rdata),
    .debug_reg_rwaddr(debug_reg_rwaddr),
    .PC(riscv_pc),
    .irq({31'd0,~key[1]}),
    .debug_reg_rdata(debug_reg_rdata)
);

reg flag;
always @(posedge clk) begin
    flag <= ~flag;
end


always @(posedge clk or negedge resetn) begin
    if(!resetn)begin
        debug_reg_rwaddr <= 5'h0;
    end
    else if(flag==1'b1) begin
        debug_reg_rwaddr <= debug_reg_rwaddr + 1'b1;
    end
    else begin
        debug_reg_rwaddr <= debug_reg_rwaddr;
    end
    
end
reg mem_ready_r0;
reg mem_ready_r1;
reg [31:0] mem_rdata_r0;
reg [31:0] mem_rdata_r1;

assign clk_o = ^{riscv_pc[31:0],debug_reg_rdata[31:0],debug_reg_rwaddr[4:0]};

wire [7:0] uart_rdata;
reg [7:0] uart_wdata;
reg uart_start;
wire uart_rxdone;
wire uart_txdone;
uart_recv
#(
	.CLK_FREQ	(50000000),
	.UART_BPS	(115200)
)
u_uart_recv(
	.clk			(clk),
	.rst_n		(resetn),
	
	.uart_rxd	(uart_rx),
	.uart_data	(uart_rdata),
	.uart_done	(uart_rxdone),
);
uart_txd
#(
	.CLK_FREQ	(50000000),
	.UART_BPS	(115200)
)
u_uart_txd(
	.clk			(clk),
	.rst_n		(resetn),

	.uart_txd	(uart_tx),
	.uart_en		(uart_start),

	.uart_data	(uart_wdata),
    .uart_tx_done (uart_txdone)
	);
reg uart_rxdone_r0;
wire uart_rxdone_pos;
always @(posedge clk) begin
    uart_rxdone_r0 <= uart_rxdone;
end
assign uart_rxdone_pos = uart_rxdone &(~uart_rxdone_r0);
assign mem_ready = (mem_addr[31:16] > 16'h0) ? mem_ready_r0 : mem_ready_r1;
assign mem_rdata = (mem_addr[31:16] > 16'h0) ? mem_rdata_r0 : mem_rdata_r1;
reg [1:0] uart_state;
reg [3:0] uart_cnt;
reg uart_send_state;
parameter uart_send = 1'b0;
parameter uart_tx_wait = 1'b1;

parameter uart_init = 2'b00;
parameter uart_wait = 2'b01;
parameter uart_work = 2'b10;

reg [15:0] uart_delay_cnt;
always@(posedge  clk or negedge resetn)begin
    if(!resetn) begin
        uart_delay_cnt <= 16'h0;
    end
    else if(uart_state == uart_wait) begin
        uart_delay_cnt <= uart_delay_cnt + 1'b1;
    end
    else begin
        uart_delay_cnt <= 16'h0;
    end
end
always@(posedge clk or negedge resetn) begin
    if(!resetn) begin
        mem_ready_r1 <= 1'b0;
        cpu_reste <= 1'b0;
        uart_wdata <= 8'h0;
        uart_state <= uart_init;
        uart_cnt <= 4'h0;
        uart_start <= 1'b0;
        uart_send_state <= uart_send;
    end
    else begin
        case(uart_state)
        uart_init:begin
            case(uart_cnt)
            4'h0:begin
                uart_wdata <= 8'hfe;
                case(uart_send_state)
                uart_send:begin
                    uart_send_state <= uart_tx_wait;
                    uart_start <= 1'b1;
                end
                uart_tx_wait:begin
                    uart_start <= 1'b0;
                    if(uart_txdone)begin
                        uart_send_state <= uart_send;
                        uart_cnt <= 4'h1;
                    end
                end
                endcase
            end
            4'h1:begin
                uart_wdata <= 8'hfe;
                case(uart_send_state)
                uart_send:begin
                    uart_send_state <= uart_tx_wait;
                    uart_start <= 1'b1;
                end
                uart_tx_wait:begin
                    uart_start <= 1'b0;
                    if(uart_txdone)begin
                        uart_send_state <= uart_send;
                        uart_cnt <= 4'h2;
                    end
                end
                endcase
            end
            4'h2:begin
                uart_wdata <= 8'hfe;
                case(uart_send_state)
                uart_send:begin
                    uart_send_state <= uart_tx_wait;
                    uart_start <= 1'b1;
                end
                uart_tx_wait:begin
                    uart_start <= 1'b0;
                    if(uart_txdone)begin
                        uart_send_state <= uart_send;
                        uart_cnt <= 4'h3;
                    end
                end
                endcase
            end
            4'h3:begin
                uart_wdata <= 8'hfe;
                case(uart_send_state)
                uart_send:begin
                    uart_send_state <= uart_tx_wait;
                    uart_start <= 1'b1;
                end
                uart_tx_wait:begin
                    uart_start <= 1'b0;
                    if(uart_txdone)begin
                        uart_send_state <= uart_send;
                        uart_cnt <= 4'h4;
                    end
                end
                endcase
            end
            4'h4:begin
                uart_wdata <= 8'hfe;
                case(uart_send_state)
                uart_send:begin
                    uart_send_state <= uart_tx_wait;
                    uart_start <= 1'b1;
                end
                uart_tx_wait:begin
                    uart_start <= 1'b0;
                    if(uart_txdone)begin
                        uart_send_state <= uart_send;
                        uart_cnt <= 4'h5;
                    end
                end
                endcase
            end
            4'h5:begin
                uart_wdata <= 8'hfe;
                case(uart_send_state)
                uart_send:begin
                    uart_send_state <= uart_tx_wait;
                    uart_start <= 1'b1;
                end
                uart_tx_wait:begin
                    uart_start <= 1'b0;
                    if(uart_txdone)begin
                        uart_send_state <= uart_send;
                        uart_cnt <= 4'h6;
                    end
                end
                endcase
            end
            4'h6:begin
                uart_wdata <= 8'hfe;
                case(uart_send_state)
                uart_send:begin
                    uart_send_state <= uart_tx_wait;
                    uart_start <= 1'b1;
                end
                uart_tx_wait:begin
                    uart_start <= 1'b0;
                    if(uart_txdone)begin
                        uart_send_state <= uart_send;
                        uart_cnt <= 4'h0;
                        uart_state <= uart_wait;
                    end
                end
                endcase
            end
            default:begin
                uart_cnt <= uart_cnt;
            end
            endcase
        end
        uart_wait:begin
            if(uart_delay_cnt == 16'd49999) begin
                uart_state <= uart_work;
                uart_send_state <= uart_send;
                uart_cnt <= 4'h0;
                cpu_reste <= 1'b1;
                mem_ready_r1 <= 1'b0;
            end
        end
        uart_work:begin
            if(mem_valid == 1'b0) begin
                mem_ready_r1 <= 1'b0;
                uart_cnt <= 4'h0;
            end
            if((mem_addr[31:16] == 16'h0)) begin
                if(mem_valid)begin
                    if(mem_wstrb == 4'b0000)begin
                        case(uart_cnt)
                        4'h0:begin
                            if(mem_instr) begin
                                uart_wdata <= 8'h80;//请求取指令
                            end
                            else begin
                                uart_wdata <= 8'hA0;//读数据
                            end
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    uart_send_state <= uart_send;
                                    uart_cnt <= 4'h1;
                                end
                            end
                            endcase
                        end
                        4'h1:begin
                            uart_wdata <= mem_addr[15:8];//发送地址
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    uart_send_state <= uart_send;
                                    uart_cnt <= 4'h2;
                                end
                            end
                            endcase
                        end
                        4'h2:begin
                            uart_wdata <= mem_addr[7:0];//发送地址
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    uart_send_state <= uart_send;
                                    uart_cnt <= 4'h3;
                                end
                            end
                            endcase
                        end
                        4'h3:begin
                            if(uart_rxdone_pos) begin
                                mem_rdata_r1[31:24] <= uart_rdata;//
                                uart_cnt <= 4'h4;
                            end
                        end
                        4'h4:begin
                            if(uart_rxdone_pos) begin
                                mem_rdata_r1[23:16] <= uart_rdata;
                                uart_cnt <= 3'h5;
                            end
                        end
                        4'h5:begin
                            if(uart_rxdone_pos) begin
                                mem_rdata_r1[15:8] <= uart_rdata;
                                uart_cnt <= 4'h6;
                            end
                        end
                        4'h6:begin
                            if(uart_rxdone_pos) begin
                                mem_rdata_r1[7:0] <= uart_rdata;
                                uart_cnt <= 4'h7;
                                mem_ready_r1 <= 1'b1;
                            end
                        end

                        4'h7:begin
                            mem_rdata_r1 <= mem_rdata_r1;
                        end
                        endcase
                    end
                    else begin
                        
                        case(uart_cnt)
                        4'h0:begin
                            uart_wdata <= {4'h9,mem_wstrb[3:0]};//8'h9x命令
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    uart_send_state <= uart_send;
                                    uart_cnt <= 4'h1;
                                end
                            end
                            endcase
                        end
                        4'h1:begin
                            uart_wdata <= mem_addr[15:8];//发送地址
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    uart_send_state <= uart_send;
                                    uart_cnt <= 4'h2;
                                end
                            end
                            endcase
                        end
                        4'h2:begin
                            uart_wdata <= mem_addr[7:0];//发送地址
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    uart_send_state <= uart_send;
                                    uart_cnt <= 4'h3;
                                end
                            end
                            endcase
                        end
                        4'h3:begin
                            uart_wdata <= mem_wdata[31:24];
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    case(mem_wstrb)
                                        4'b0001:uart_cnt <= 4'h7;
                                        4'b0010:uart_cnt <= 4'h7;
                                        4'b0100:uart_cnt <= 4'h7;
                                        4'b1000:uart_cnt <= 4'h7;
                                        default:uart_cnt <= 4'h4;
                                    endcase
                                    uart_send_state <= uart_send;
                                end
                            end
                            endcase
                        end

                        4'h4:begin
                            uart_wdata <= mem_wdata[23:16];
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    case(mem_wstrb)
                                        4'b0011:uart_cnt <= 4'h7;
                                        4'b1100:uart_cnt <= 4'h7;
                                        default:uart_cnt <= 4'h5;
                                    endcase
                                    uart_send_state <= uart_send;
                                end
                            end
                            endcase
                        end

                        4'h5:begin
                            uart_wdata <= mem_wdata[15:8];
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    uart_send_state <= uart_send;
                                    uart_cnt <= 4'h6;
                                end
                            end
                            endcase
                        end

                        4'h6:begin
                            uart_wdata <= mem_wdata[7:0];
                            case(uart_send_state)
                            uart_send:begin
                                uart_send_state <= uart_tx_wait;
                                uart_start <= 1'b1;
                            end
                            uart_tx_wait:begin
                                uart_start <= 1'b0;
                                if(uart_txdone)begin
                                    uart_send_state <= uart_send;
                                    uart_cnt <= 4'h7;
                                end
                            end
                            endcase
                        end

                        4'h7:begin
                            uart_cnt <= 4'h7;
                            mem_ready_r1 <= 1'b1;
                        end

                        endcase
                    end
                end
            end
        end
        endcase
    end
end
reg [31:0] memory [0:20];
always @(posedge clk or negedge resetn) begin
        if(!resetn)begin

            mem_ready_r0 <= 0;
        end
        else begin
		    mem_ready_r0 <= 0;
            if (resetn && mem_valid && !mem_ready) begin
                (* parallel_case *)
                case (1)
                    !mem_wstrb && ((mem_addr[15:0] >> 2) < 20) && (mem_addr[31:16] > 16'h0): begin
                        mem_rdata_r0 <= memory[mem_addr[15:0] >> 2];
                        mem_ready_r0 <= 1;
                    end
                    |mem_wstrb && ((mem_addr[15:0] >> 2) < 20) && (mem_addr[31:16] > 16'h0): begin
                        if (mem_wstrb[0]) memory[mem_addr[15:0] >> 2][ 7: 0] <= mem_wdata[ 7: 0];
                        if (mem_wstrb[1]) memory[mem_addr[15:0] >> 2][15: 8] <= mem_wdata[15: 8];
                        if (mem_wstrb[2]) memory[mem_addr[15:0] >> 2][23:16] <= mem_wdata[23:16];
                        if (mem_wstrb[3]) memory[mem_addr[15:0] >> 2][31:24] <= mem_wdata[31:24];
                        mem_ready_r0 <= 1;
                    end
                    mem_addr == 32'h1000_0000: begin
                        if(|mem_wstrb) begin
                            out_byte <= mem_wdata;
                            mem_ready_r0 <= 1;
                        end
                        else begin
                            mem_rdata_r0[31:0] <={24'h0, out_byte[7:0]};
                            mem_ready_r0 <= 1;
                        end
                    end
                endcase
            end
        end
	end
endmodule
